/*
 * Saphre - Suffix Arrays for Phrase Extraction
 * Copyright (C) 2013 
 * Dale Gerdemann - Tübingen, Germany 
 * Niko Schenk - Frankfurt am Main, Germany
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
package serialization;

import saphre.core.SaphreBase;
import util.Interval;
import saphre.core.Store;
import saphre.core.SuffixArray;
import util.tokenization_io.Tokenizer;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.io.*;
import java.util.UUID;
import saphre.concordance.Concordance;
import saphre.concordance.ConcordanceOverlap;
import util.tokenization_io.BoundarySymbols;

/**
 * Saphre Web Router
 * 
 * @author Niko Schenk, Zeeshan Mustafa
 */
public class SaphreWebRouter {
    
    /**
     * 
     */
    public class SaphreDeserializedObject {
        Store store;
        Tokenizer token;
        SuffixArray sa;
        SuffixArray pa;
        Interval top;
        BoundarySymbols tc;
        Concordance concord;
        ConcordanceOverlap concordOver;

    }

    /**
     * 
     * @param corpusFolderPath
     * @return
     * @throws Exception 
     */
    public SaphreDeserializedObject deserializeSaphreFromDisk(String corpusFolderPath) throws Exception {
        SaphreDeserializedObject sdo = new SaphreDeserializedObject();
        String serializePath = corpusFolderPath + "/../serialize";
        System.out.println(serializePath);
        
        File file = new File(serializePath);

        String concordPath = serializePath + "/concord.ser";
        String concordOverPath = serializePath + "/concordOver.ser";
        String paPath = serializePath + "/pa.ser";
        String saPath = serializePath + "/sa.ser";
        String storePath = serializePath + "/store.ser";
        String tcPath = serializePath + "/tc.ser";
        String tokenPath = serializePath + "/token.ser";
        String topPath = serializePath + "/top.ser";

        if (file.exists() && !file.isFile()) {
            System.out.println("Deserializing...");

            sdo.concord = (Concordance) readObjectFromFile(concordPath);
            sdo.concordOver = (ConcordanceOverlap) readObjectFromFile(concordOverPath);
            sdo.pa = (SuffixArray) readObjectFromFile(paPath);
            sdo.sa = (SuffixArray) readObjectFromFile(saPath);
            sdo.tc = (BoundarySymbols) readObjectFromFile(tcPath);
            sdo.store = (Store) readObjectFromFile(storePath);
            sdo.token = (Tokenizer) readObjectFromFile(tokenPath);
            sdo.top = (Interval) readObjectFromFile(topPath);
            System.out.println("...done.");
            return sdo;
        }
        else {
            System.out.println("... could not find binary (.ser) files.");
        }

        return null;
    }

    /**
     * 
     * @param path
     * @return
     * @throws Exception 
     */
    public Object readObjectFromFile(String path) throws Exception {
        File file = new File(path);
        if (file.exists()) {
            Object obj = null;
            FileInputStream fis = null;
            ObjectInputStream in = null;

            fis = new FileInputStream(path);
            in = new ObjectInputStream(fis);
            obj = in.readObject();
            in.close();

            return obj;
        }
        return null;
    }

   /**
     * Make a new directory for the "loadOptions" and write regex, boundary and norms
     * to this folder.
     * @param corpusFolderPath
     * @param corpusBoundary
     * @param corpusRegEx
     * @param corpusNorms
     * @return
     * @throws Exception 
     */
    public SaphreSerializerMeta loadCorpusFromDisk(String corpusFolderPath, String corpusBoundary, String corpusRegEx, String corpusNorms) throws Exception {

        File file = new File(corpusFolderPath);
        String optionsPath = corpusFolderPath + "/../loadOptions";

        if (file.exists() && !file.isFile()) {
            file = new File(optionsPath);

            if (!file.exists()) {
                file.mkdir();
            }

            File directory = new File(optionsPath);
            File[] files = directory.listFiles();
            for (File file1 : files) {
                if (!file1.delete()) {
                    System.out.println("Failed to delete " + file1);
                }
            }

            directory = null;
            file = null;
            files = null;
            file = null;

            String boundaryPath = optionsPath + "/boundary";
            String regexPath = optionsPath + "/regex";
            String normPath = optionsPath + "/norms";

            writeToFile(boundaryPath, corpusBoundary);
            writeToFile(regexPath, corpusRegEx);
            writeToFile(normPath, corpusNorms);

            Map<String, List<Interval>> delMap =
                    new TreeMap<String, List<Interval>>();
            SaphreBase saphreBase = new SaphreBase(delMap, corpusFolderPath, regexPath, normPath, boundaryPath, true, UUID.randomUUID());

            saphreBase.invoke();

            SaphreSerializerMeta ssm = saphreBase.getSaphreSerializerMeta();

            return ssm;
        }
        else {
            System.out.println("Something wrong with the path...");
        }
        return null;
    }

    /*
     * 
     */
    private boolean writeToFile(String path, String text) {
        try {

            FileWriter fstream = new FileWriter(path);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(text);
            out.close();
            fstream.close();
            ;
            return true;
        }
        catch
                (Exception e) {
            return false;
        }
    }
    
    
    /**
     * Test method.
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        SaphreWebRouter swr = new SaphreWebRouter();
        String corpusPath = "src/main/resources/corpusProjects/testcorpus/corpus";
        
        swr.loadCorpusFromDisk(corpusPath, ".\n" +
                ",\n" +
                "!\n" +
                "?\n" +
                "*\n" +
                "(\n" +
                ")\n" +
                "\"\n" +
                "'\n" +
                ";\n" +
                ":\n" +
                "[\n" +
                "]\n" +
                "â€”\n" +
                "-\n", "#\\n\\n+|\n" +
                "--|\n" +
                "Mr.|\n" +
                "\\w+in'|   # shortened -ing word\n" +
                "\\w+s'|    # apostrophe after plural\n" +
                "'em|\n" +
                "s'pose|\n" +
                "o'clock|\n" +
                "'balmed|\n" +
                "reg'lar|\n" +
                "sou'-wester|\n" +
                "\\w+([â€™']([dmst]|re|ve|ll))?|  # apostrophe: \n" +
                "\\w+(-\\w+)+|\n" +
                "\\p{P}        # punctuation\n", "not yet used");
    }
}


